﻿using System;
using System.Collections.Generic;
using System.Text;
using LumaQQ.NET.Packets.In;
using LumaQQ.NET.Packets.In._08;
using LumaQQ.NET.Packets.Out;
using LumaQQ.NET.Packets.Out._08;

namespace LumaQQ.NET.Packets
{
    public class _08BasicFamilyParser : IParser
    {
        private int offset;
        private int length;

        private PacketHistory history;

        public _08BasicFamilyParser()
        {
            history = new PacketHistory();
        }

        /* (non-Javadoc)
          * @see edu.tsinghua.lumaqq.qq.packets.IParser#accept(java.nio.ByteBuffer)
          */
        public bool Accept(ByteBuffer buf)
        {
            //保存偏移
            offset = buf.Position;
            int bufferLength = buf.Remaining();
            if (bufferLength <= 0)
                return false;
            bool accept = CheckTcp(buf);
            if (!accept)
                accept = CheckUdp(buf);
            return accept;
        }
        /**
         * 检查一个包是否是udp包
         *
         * @param buf ByteBuffer
         * @return true表示是，false表示否
         */
        private bool CheckUdp(ByteBuffer buf)
        {
            if ((_08QQ.HeaderFamily)buf.Get(offset) == _08QQ.HeaderFamily.QQ_HEADER_BASIC_FAMILY)
            {
                // 首先检查是否UDP方式
                length = buf.Length - buf.Position;
                if ((_08QQ.TailFamily)buf.Get(offset + length - 1) == _08QQ.TailFamily.QQ_TAIL_BASIC_FAMILY)
                    return true;
            }
            return false;
        }

        /**
         * 检查一个包是否是tcp包
         *
         * @param buf ByteBuffer
         * @return true表示是
         */
        private bool CheckTcp(ByteBuffer buf)
        {

            //buffer length不大于2则连个长度字段都没有
            int bufferLength = buf.Length - buf.Position;
            if (bufferLength < 2) return false;
            // 如果可读内容小于包长，则这个包还没收完
            length = buf.GetChar(offset);
            if (length <= 0 || length > bufferLength)
                return false;
            // 再检查包头包尾
            if ((_08QQ.HeaderFamily)buf.Get(offset + 2) == _08QQ.HeaderFamily.QQ_HEADER_BASIC_FAMILY)
                if ((_08QQ.TailFamily)buf.Get(offset + length - 1) == _08QQ.TailFamily.QQ_TAIL_BASIC_FAMILY)
                    return true;
            return false;

        }

        public int GetLength(ByteBuffer buf)
        {
            return length;
        }

        public bool IsDuplicate(_08InPacket inpacket)
        {
            return history.Check(inpacket, true);
        }

        /**
         * 得到包的命令和序号
         *
         * @param buf
         */
        private _08QQ.Command GetCommand(ByteBuffer buf, QQUser user)
        {
            if (!user.IsUdp)
            {
                return (_08QQ.Command)buf.GetUShort(offset + 5);
            }
            else
            {
                return (_08QQ.Command)buf.GetUShort(offset + 3);
            }
        }

        /* (non-Javadoc)
          * @see edu.tsinghua.lumaqq.qq.packets.IParser#parseIncoming(java.nio.ByteBuffer, int, edu.tsinghua.lumaqq.qq.beans.QQUser)
          */
        public _08InPacket ParseIncoming(ByteBuffer buf, int len, QQUser user)
        {
            try
            {
                switch (GetCommand(buf, user))
                {
                    case _08QQ.Command.QQ_CMD_TOUCH://由luna添加
                        return new _08TouchLoginReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_1://由luna添加
                        return new _08LoginToken1ReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_2://由luna添加
                        return new _08LoginToken2ReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CHECK_PASSWORD://由luna添加
                        return new _08LoginKeyReplyPacket(buf, len, user);
                    //以下两句被luna注释掉
                    /*case _08QQ.QQ_CMD_GET_LOGIN_TOKEN:
                         return new GetLoginTokenReplyPacket(buf, len, user);*/
                    case _08QQ.Command.QQ_CMD_FIRST_LOGIN:
                        return new _08FirstLoginReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_KEEP_ALIVE:
                        return new _08KeepAliveReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_MODIFY_INFO:
                        return new _08ModifyInfoReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_ADD_FRIEND_EX:
                        return new AddFriendExReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_AUTH_QUESTION_OP:
                        return new AuthQuestionOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_AUTH_INFO_OP:
                        return new _08AuthInfoOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SEARCH_USER:
                        return new SearchUserReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_DELETE_FRIEND:
                        return new DeleteFriendReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_REMOVE_SELF:
                        return new RemoveSelfReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_ADD_FRIEND_AUTH:
                        return new AddFriendAuthResponseReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GET_USER_INFO:
                        return new GetUserInfoReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CHANGE_STATUS:
                        return new ChangeStatusReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SEND_IM:
                        return new SendIMReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_RECV_IM:
                        //            		log.info("_08InputStatusPacket 已经被执行");
                        //            		return new _08InputStatusPacket(buf, len, user);        		
                        //            		log.debug("ReceiveIMPacket 已经被执行");
                        return new ReceiveIMPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGIN:
                        //return new LoginReplyPacket(buf, len, user);
                        //log.debug("07登陆请求包已经被回复！");
                        return new _08LoginReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GET_FRIEND_LIST:
                        //log.debug("获得好友列表包已经被回复！");
                        return new GetFriendListReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GET_ONLINE_OP:
                        //log.debug("获得在线好友列表包已经被回复！");
                        return new _08GetOnlineOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_RECV_MSG_SYS:
                        return new SystemNotificationPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
                        return new FriendChangeStatusPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_UPLOAD_GROUP_FRIEND:
                        return new UploadGroupFriendReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_DOWNLOAD_GROUP_FRIEND:
                        return new DownloadGroupFriendReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GROUP_DATA_OP:
                        return new GroupDataOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_FRIEND_DATA_OP:
                        return new FriendDataOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CLUSTER_CMD:
                        return new ClusterCommandReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_REQUEST_KEY:
                        return new GetKeyReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_ADVANCED_SEARCH:
                        return new AdvancedSearchUserReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CLUSTER_DATA_OP:
                        return new GetTempClusterOnlineMemberReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_AUTHORIZE:
                        return new _08AuthorizeReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SIGNATURE_OP:
                        return new _08SignatureOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_WEATHER_OP:
                        return new WeatherOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_USER_PROPERTY_OP:
                        return new UserPropertyOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_FRIEND_LEVEL_OP:
                        return new FriendLevelOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SEND_SMS:
                        return new SendSMSReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_TEMP_SESSION_OP:
                        return new TempSessionOpReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_PRIVACY_DATA_OP:
                        return new PrivacyDataOpReplyPacket(buf, len, user);
                    default:
                        return new UnknownInPacket(buf, len, user);
                }
            }
            catch (PacketParseException e)
            {
                // 如果解析失败，返回null
                buf.Position = offset;
                return new UnknownInPacket(buf, len, user);
            }
        }

        /* (non-Javadoc)
          * @see edu.tsinghua.lumaqq.qq.packets.IParser#parseOutcoming(java.nio.ByteBuffer, int, edu.tsinghua.lumaqq.qq.beans.QQUser)
          */
        public _08OutPacket ParseOutcoming(ByteBuffer buf, int len, QQUser user)
        {
            try
            {
                switch (GetCommand(buf, user))
                {
                    case _08QQ.Command.QQ_CMD_TOUCH://由luna添加
                        //System.out.println("Touch包已经被发送");
                        return new _08TouchLoginPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_1://由luna添加
                        //System.out.println("Login Token 1 已经被发送");
                        return new _08LoginToken1Packet(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_2://由luna添加
                        //System.out.println("Login Token 2 已经被发送");
                        return new _08LoginToken2Packet(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CHECK_PASSWORD://由luna添加
                        //System.out.println("Login Key 已经被发送");
                        return new _08LoginKeyPacket(buf, len, user);
                    /*case _08QQ.Command.QQ_CMD_GET_LOGIN_TOKEN:
                         return new GetLoginTokenPacket(buf, len, user);*/
                    case _08QQ.Command.QQ_CMD_KEEP_ALIVE:
                        return new _08KeepAlivePacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_MODIFY_INFO:
                        return new _08ModifyInfoPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SEARCH_USER:
                        return new SearchUserPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_ADD_FRIEND_EX:
                        return new AddFriendExPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_AUTH_INFO_OP:
                        //System.out.println("auth infp op 包已经被发送");
                        return new _08AuthInfoOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_AUTH_QUESTION_OP:
                        return new AuthQuestionOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_DELETE_FRIEND:
                        return new DeleteFriendPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_REMOVE_SELF:
                        return new RemoveSelfPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_ADD_FRIEND_AUTH:
                        return new AddFriendAuthResponsePacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GET_USER_INFO:
                        return new GetUserInfoPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CHANGE_STATUS:
                        return new ChangeStatusPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SEND_IM:
                        return new SendIMPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_RECV_IM:
                        return new ReceiveIMReplyPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGIN:
                        //return new LoginPacket(buf, len, user);
                        return new _08LoginPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_FIRST_LOGIN:
                        return new _08FirstLoginPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GET_FRIEND_LIST:
                        return new GetFriendListPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GET_ONLINE_OP:
                        return new _08GetOnlineOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_UPLOAD_GROUP_FRIEND:
                        return new UploadGroupFriendPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_DOWNLOAD_GROUP_FRIEND:
                        return new DownloadGroupFriendPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_GROUP_DATA_OP:
                        return new GroupDataOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_FRIEND_DATA_OP:
                        return new FriendDataOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_ADVANCED_SEARCH:
                        return new AdvancedSearchUserPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_CLUSTER_CMD:
                        return new ClusterCommandPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_LOGOUT:
                        return new LogoutPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_AUTHORIZE:
                        return new _08AuthorizePacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SIGNATURE_OP:
                        return new _08SignatureOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_WEATHER_OP:
                        return new WeatherOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_USER_PROPERTY_OP:
                        return new UserPropertyOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_FRIEND_LEVEL_OP:
                        return new FriendLevelOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_SEND_SMS:
                        return new SendSMSPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_TEMP_SESSION_OP:
                        return new TempSessionOpPacket(buf, len, user);
                    case _08QQ.Command.QQ_CMD_PRIVACY_DATA_OP:
                        return new PrivacyDataOpPacket(buf, len, user);
                    default:
                        return new UnknownOutPacket(buf, len, user);
                }
            }
            catch (PacketParseException e)
            {
                // 如果解析失败，返回一个未知包
                buf.Position = offset;
                return new UnknownOutPacket(buf, len, user);
            }
        }

        /* (non-Javadoc)
          * @see edu.tsinghua.lumaqq.qq.packets.IParser#isDuplicatedNeedReply(edu.tsinghua.lumaqq.qq.packets._08InPacket)
          */
        public bool IsDuplicatedNeedReply(_08InPacket inpackage)
        {
            return inpackage.Command == _08QQ.Command.QQ_CMD_RECV_IM;
        }

        /* (non-Javadoc)
          * @see edu.tsinghua.lumaqq.qq.packets.IParser#relocate(java.nio.ByteBuffer)
          */
        public int Relocate(ByteBuffer buf)
        {
            int offset = buf.Position;
            if (buf.Remaining() < 2)
                return offset;
            int len = buf.GetUShort(offset);
            if (len <= 0 || offset + len > buf.Length)
                return offset;
            else
                return offset + len;
        }

        /* (non-Javadoc)
          * @see edu.tsinghua.lumaqq.qq.packets.IParser#getHistory()
          */
        public PacketHistory GetHistory()
        {
            return history;
        }
    }
}
